/*
 * AbstractScheduler.cc
 *
 *  Created on: 2011-04-09
 *      Author: Jagger
 */

#include "AbstractScheduler.h"

void AbstractScheduler::initialize()
{
	processEvent = new cMessage("processEvent");
}

void AbstractScheduler::handleMessage(cMessage* msg)
{
	simtime_t processDelay = par("processDelay");

	if(msg != processEvent)
	{
		// Dostalismy nie nasz pakiet. Umiescmy go w kolejce pakietow
		// oczekujacych na wyslanie
		NetPacket* pck = check_and_cast<NetPacket*>(msg);
		bool queued = receivePacket(pck, pck->getArrivalGateId());

		if(queued)
		{
			// Jesli udalo nam sie zakolejkowac pakiet i nie przetwarzamy w tym
			// momencie zadnego pakietu, to powinnismy to zrobic teraz.
			if(!processEvent->isScheduled())
				scheduleAt(simTime() + processDelay, processEvent);
		}
		else
		{
			EV << "Packet " << pck->getName() << " discarded.\n";
			delete pck; // Pakiet zostal odrzucony
		}
	}
	else
	{
		// Otrzymalismy zdarzenie wyslania pakietu.
		// Wyciagamy pakiet z kolejki zgodnie z zaimplementowanym algorytmem
		// schedulingu i wysylamy go dalej.
		NetPacket* pck = getPacketForDeparture();

		// Uwzgledniamy opoznienie wynikajace z niedoskonalosci kanalu
		// wyjsciowego.
		cGate* out = gate("out");
		cChannel* channel = out->getChannel();
		if(channel)
		{
			simtime_t finishTime = channel->getTransmissionFinishTime();
			simtime_t delay = std::max(finishTime - simTime(), SIMTIME_ZERO);

			sendDelayed(pck, delay, out);
		}
		else
			send(pck, out);

		// Po wyslaniu pakietu sprawdzamy czy istnieje inny pakiet oczekujacy
		// na wyslanie. Jesli tak, to go przetwarzamy.
		if(hasPacketsAwaitingDeparture())
			scheduleAt(simTime() + processDelay, processEvent);
	}
}
